package com.xiaoma.mvcconfig;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.catalina.Context;
import org.apache.tomcat.util.http.LegacyCookieProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

import java.io.IOException;

/**
 * MVC 配置类。如果想全面控制Spring MVC，你可以添加自己的@Configuration，并使用@EnableWebMvc对其注解。 如果想保留Spring Boot
 * MVC的特性，并只是添加其他的MVC配置(拦截器，formatters，视图控制器等)，
 * 你可以添加自己的WebMvcConfigurerAdapter类型的@Bean（不使用@EnableWebMvc注解），
 * 
 * 如果不使用 @EnableWebMvc ， Spring Boot 默认优先依次加载一下几个filter: 1. characterEncodingFilter 用于处理编码问题。 2.
 * hiddenHttpMethodFilter
 * 浏览器form表单只支持GET与POST请求，而DELETE、PUT等method并不支持，spring3.0添加了一个过滤器，可以将这些请求转换为标准的http方法，
 * 使得支持GET、POST、PUT与DELETE请求，该过滤器为HiddenHttpMethodFilter。 3. httpPutFormContentFilter
 * 由HiddenHttpMethodFilter可知
 * ，html中的form的method值只能为post或get，我们可以通过HiddenHttpMethodFilter获取put表单中的参数键值对，
 * 而在Spring3中获取put表单的参数键值对还有另一种方法
 * ，即使用HttpPutFormContentFilter过滤器。HttpPutFormContentFilter过滤器的作为就是获取put表单的值，
 * 并将之传递到Controller中标注了method为RequestMethod
 * .put的方法中。与HiddenHttpMethodFilter不同，在form中不用添加参数名为_method的隐藏域，
 * 且method不必是post，直接写成put，但该过滤器只能接受enctype值为application
 * /x-www-form-urlencoded的表单，也就是说，在使用该过滤器时，form表单的代码必须如下：
 * <form action="" method="put" enctype="application/x-www-form-urlencoded"/> 4.
 * requestContextFilter 通过LocaleContextHolder和RequestContextHolder把Http
 * request对象基于LocalThread绑定到请求提供服务的线程上
 * 
 * 之后 Spring Boot 加载用户自定义 filter。 @WebFilter 通过此注解声明的 filter 无法通过 @Order 设置拦截顺序，默认使用采用类名的字符顺序。
 * 可以通过实例化 FilterRegistrationBean 来声明filter的过滤顺序.
 * @author Knight-Ran 2017年3月6日 下午7:27:56
 * 
 * 

当使用@EnableWebMvc则会导入DelegatingWebMvcConfiguration，继承于WebMvcConfigurationSupport
则不会使用WebMvcAutoConfiguration的配置。
 
WebMvcAutoConfiguration的注解如下：
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
        WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

所以。。。。。。。。。。。。。。。。。
@EnableWebMvc+extends WebMvcConfigurationAdapter，在扩展的类中重写父类的方法即可，这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置
extends WebMvcConfigurationSupport，在扩展的类中重写父类的方法即可，这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置
extends WebMvcConfigurationAdapter/WebMvcConfigurer，在扩展的类中重写父类的方法即可，这种方式依旧使用springboot的@EnableAutoConfiguration中的设置

 */


@EnableScheduling
@Configuration
// @ServletComponentScan
public class WebAppMvcConfigurer extends WebMvcConfigurerAdapter{
    
    /**
     * 设置自定义拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        // 国际化变化拦截器
        LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
        registry.addInterceptor(localeInterceptor);
        
        // 授权拦截器
//        registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");
        registry.addInterceptor(new SessionInterceptor()).addPathPatterns("/**");
    }
    
    
    /**
     * 设置静态资源的缓存,不使用缓存
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/html/**").addResourceLocations("classpath:/static/html/");
        
        registry.addResourceHandler("/js/plugins/**").addResourceLocations("classpath:/static/js/plugins/");
        
        registry.addResourceHandler("/ui-plugins/**").addResourceLocations("classpath:/static/ui-plugins/");
        
        registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/").setCacheControl(CacheControl.noStore());
        
        registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/").setCacheControl(CacheControl.noStore());
        
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/").setCacheControl(CacheControl.noStore());
    }
    

}
